package org.crown.project.api;

import lombok.extern.slf4j.Slf4j;
import org.crown.framework.model.ErrorCode;
import org.crown.framework.responses.ApiResponses;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

/**
 * 系统异常处理
 * @author WuFengSheng
 */
@Slf4j
@Controller
public class MyErrorController implements ErrorController {

    private static final String ERROR_PATH = "/error";

    @Override
    public String getErrorPath() {
        return ERROR_PATH;
    }

    /**
     * 除Web页面外的错误处理，比如Json/XML等
     */
    @RequestMapping(value = ERROR_PATH)
    @ResponseBody
    @ExceptionHandler(value = {Exception.class})
    public Object errorApiHandler(HttpServletRequest request, final Exception ex, final WebRequest req) {
        /**
         * javax.servlet.error.status_code
         * 该属性给出状态码，状态码可被存储，并在存储为java.lang.Integer数据类型后可被分析。
         *
         * javax.servlet.error.exception_type
         * 该属性给出异常类型的信息，异常类型可被存储，并在存储为java.lang.Class数据类型后可被分析。
         *
         * javax.servlet.error.message
         * 该属性给出确切错误消息的信息，信息可被存储，并在存储为java.lang.String数据类型后可被分析。
         *
         * javax.servlet.error.request_uri
         * 该属性给出有关URL调用Servlet的信息，信息可被存储，并在存储为java.lang.String数据类型后可被分析。
         *
         * javax.servlet.error.exception
         * 该属性给出异常产生的信息，信息可被存储，并在存储为java.lang.Throwable数据类型后可被分析。
         *
         * javax.servlet.error.servlet_name
         * 该属性给出Servlet的名称，名称可被存储，并在存储为java.lang.String数据类型后可被分析。
         */
        Integer status = (Integer) request.getAttribute("javax.servlet.error.status_code");
        String message = "" + request.getAttribute("javax.servlet.error.message");
        String requestUri = "" + request.getAttribute("javax.servlet.error.request_uri");
        Throwable exception = (Throwable) request.getAttribute("javax.servlet.error.exception");

        log.info("ErrorController={}, {}, {}", status, requestUri, message);

        if (requestUri != null && requestUri.startsWith(BaseApi.getApiPathPrefix())) {

            if (status == null) {
                status = 500;
                message = "Internal server error";
            }
            return ApiResponses.failure(ErrorCode.builder().status(status).error(message).msg(message).build());
        } else {
            switch (status) {
                case 404:
                    return new ModelAndView("error/404.html");
                case 500:
                    return new ModelAndView("error/500.html");
                default:
                    return new ModelAndView("error/business.html");
            }
        }
    }

}
